package test.action
{

import flexunit.framework.TestCase;
import flexunit.framework.TestSuite;

import com.fit4as.fit.Fixture;
import com.fit4as.fit.ActionFixture;
import com.fit4as.fit.Parse;
import com.fit4as.util.io.StringWriter;


public class ActionFixtureTest extends TestCase
{

    public function ActionFixtureTest( methodName : String ) 
    {
        super( methodName );
    }


    public static function suite() : TestSuite 
    {
        var ts : TestSuite = new TestSuite();
        
		//"start" instantiates a new actor
        ts.addTest( new ActionFixtureTest("startShouldCreateActor"));

		//Keep actor until start is called again 
		ts.addTest( new ActionFixtureTest("actorShouldRemainTheSameWhenInstantiatingActionFixture"));
		ts.addTest( new ActionFixtureTest("callingStartShouldChangetheActor"));
        
    	//"enter" calls the method given by the second cell with parameter given by the third cell    
        ts.addTest( new ActionFixtureTest("enterShouldCallMethodFromTableWithOneParameterFromTable"));
        
    	//"press" calls the method given by the second cell    
        ts.addTest( new ActionFixtureTest("pressShouldCallMethodFromTableWithoutParameters"));
        
        //"check" compares the method given by the second cell against the value given by the third cell
        ts.addTest( new ActionFixtureTest("checkShouldReturnRightIfTableValueEqualsActorValue"));
        ts.addTest( new ActionFixtureTest("checkShouldReturnWrongIfTableValueNotEqualsTableValue"));
        ts.addTest( new ActionFixtureTest("checkShouldReturnErrorIfErrorOccursAndTableValueNotEqualsError"));
        ts.addTest( new ActionFixtureTest("checkShouldReturnRightIfErrorOccursAndTableValueEqualsError"));

		//The type of a enter value is determined by the signature of the enter method. If the return type is 
		//complex, the actor needs to extend parse. 
        ts.addTest( new ActionFixtureTest("typeOfEnterParameterShouldBeDeterminedByMethodSignature"));

		//The type of a check value is determined by the return type of the method to be checked. If the type is 
		//complex, it has to implement the function equals( other : * ) : Boolean to make this work
        ts.addTest( new ActionFixtureTest("checkShouldDetermineTypeFromMethod"));
        return ts;
    }
    
    private var fixture : Fixture;
    
    override public function setUp() : void
    {
		var table : Parse = Parse.createParse("<table>" 
			+ "<tr><td>com.fit4as.fit.ActionFixture</td></tr>" 
			+ "<tr><td>start</td><td>test.action.TestActor</td></tr>" 
			+ "</table>");
				
    	fixture = new Fixture();
    	ActionFixture.actor = null;	
		fixture.doTables( table );    
	}

	[test]
	public function startShouldCreateActor() : void
	{
		//assertTrue("expected to fail", false );
		assertTrue("actor should be instance of TestActor, actual:" + ActionFixture.actor + ".", 
			ActionFixture.actor is TestActor );
	}
	
	[test]
	public function actorShouldRemainTheSameWhenInstantiatingActionFixture() : void
	{
		var table : Parse = Parse.createParse("<table>" 
		    + "<tr><td>com.fit4as.fit.ActionFixture</td></tr>" // same fixture class as in setUp
			+ "</table>");
				
		var saveActor : Object = ActionFixture.actor;
    	fixture = new Fixture();
    	fixture.doTables( table );    
		
		assertTrue( "actor should not change", saveActor == ActionFixture.actor );    	
	}
	
	[test]
	public function callingStartShouldChangetheActor() : void
	{
		var table : Parse = Parse.createParse("<table>" 
		    + "<tr><td>com.fit4as.fit.ActionFixture</td></tr>" // same fixture class as in setUp
		    + "<tr><td>start</td><td>test.action.TestActor</td></tr>" 
			+ "</table>");

		var saveActor : Object = ActionFixture.actor;
    	fixture = new Fixture();
    	fixture.doTables( table );    
		
		assertFalse( "actor should change", saveActor == ActionFixture.actor );    	
	}

	[test]	
	public function enterShouldCallMethodFromTableWithOneParameterFromTable() : void
	{
		var expectedName : String = "test";
		var table : Parse = Parse.createParse("<table>" 
		    + "<tr><td>com.fit4as.fit.ActionFixture</td></tr>" // same fixture class as in setUp
			+ "<tr><td>enter</td><td>setName</td><td>" 
			+ expectedName
			+ "</td></tr>" 
			+ "</table>");
				
    	TestActor( ActionFixture.actor ).clearName();
    	fixture = new Fixture();
    	
		fixture.doTables( table );
		assertEquals("name should be " + expectedName, expectedName, TestActor( ActionFixture.actor ).name() );
	}
	
	[test]
	public function typeOfEnterParameterShouldBeDeterminedByMethodSignature() : void
	{
		var expectedId : String = "test";
		var table : Parse = Parse.createParse("<table>" 
		    + "<tr><td>com.fit4as.fit.ActionFixture</td></tr>" // same fixture class as in setUp
			+ "<tr><td>enter</td><td>setComplexObject</td><td>" 
			+ expectedId
			+ "</td></tr>" 
			+ "</table>");
				
    	TestActor( ActionFixture.actor ).setComplexObject( null );
    	fixture = new Fixture();
    	
		fixture.doTables( table );
		assertEquals("complexObject.id should be " + expectedId, expectedId, TestActor( ActionFixture.actor ).complexObject().id );
	}
	
	[test]
	public function pressShouldCallMethodFromTableWithoutParameters() : void
	{
		var table : Parse = Parse.createParse("<table>" 
		    + "<tr><td>com.fit4as.fit.ActionFixture</td></tr>" // same fixture class as in setUp
			+ "<tr><td>press</td><td>clearName</td></tr>" 
			+ "</table>");
				
    	var name : String = "test";
    	TestActor( ActionFixture.actor ).setName( name );
    	fixture = new Fixture();
    	
		fixture.doTables( table );
		assertEquals("name should be empty", "", TestActor( ActionFixture.actor ).name() );
	}

	[test]
	public function checkShouldReturnRightIfTableValueEqualsActorValue() : void
	{
		var table : Parse = Parse.createParse("<table>" 
		    + "<tr><td>com.fit4as.fit.ActionFixture</td></tr>" // same fixture class as in setUp
			+ "<tr><td>check</td><td>name</td><td>test</td></tr>" 
			+ "</table>");
				
    	var name : String = "test";
    	TestActor( ActionFixture.actor ).setName( name );
    	fixture = new Fixture();
    	
		fixture.doTables( table );
		assertCount( fixture, 1, 0, 0, 0);
	}
	
	[test]
	public function checkShouldReturnWrongIfTableValueNotEqualsTableValue() : void
	{
		var table : Parse = Parse.createParse("<table>" 
		    + "<tr><td>com.fit4as.fit.ActionFixture</td></tr>" // same fixture class as in setUp
			+ "<tr><td>check</td><td>name</td><td>something other than test</td></tr>" 
			+ "</table>");
				
    	var name : String = "test";
    	TestActor( ActionFixture.actor ).setName( name );
    	fixture = new Fixture();
    	
		fixture.doTables( table );
		assertCount( fixture, 0, 1, 0, 0);
	}

	[test]	
	public function checkShouldReturnErrorIfErrorOccursAndTableValueNotEqualsError() : void
	{
		var table : Parse = Parse.createParse("<table>" 
		    + "<tr><td>com.fit4as.fit.ActionFixture</td></tr>" // same fixture class as in setUp
			+ "<tr><td>check</td><td>not existent</td><td>something other than test</td></tr>" 
			+ "</table>");
				
    	fixture = new Fixture();
    	
		fixture.doTables( table );
		assertCount( fixture, 0, 0, 0, 1);
	}
	
	[test]
	public function checkShouldReturnRightIfErrorOccursAndTableValueEqualsError() : void
	{
		var table : Parse = Parse.createParse("<table>" 
		    + "<tr><td>com.fit4as.fit.ActionFixture</td></tr>" // same fixture class as in setUp
			+ "<tr><td>check</td><td>throwError</td><td>error</td></tr>" 
			+ "</table>");
				
    	fixture = new Fixture();
    	
		fixture.doTables( table );
		assertCount( fixture, 1, 0, 0, 0);
	}
	
	[test]
	public function checkShouldDetermineTypeFromMethod() : void
	{
		var expectedId : String = "test";
		var table : Parse = Parse.createParse("<table>" 
		    + "<tr><td>com.fit4as.fit.ActionFixture</td></tr>" // same fixture class as in setUp
			+ "<tr><td>check</td><td>complexObject</td><td>" 
			+ expectedId
			+ "</td></tr>" 
			+ "</table>");
		
    	TestActor( ActionFixture.actor ).setComplexObject( new ComplexObject( expectedId ));
    	fixture = new Fixture();
    	
		fixture.doTables( table );
		assertCount( fixture, 1, 0, 0, 0);
	}
	
	private function assertCount( fixture : Fixture, right : int, wrong : int, ignores : int, exceptions : int ) : void
	{
		if( fixture.counts.right != right 
		    || fixture.counts.wrong != wrong 
		    || fixture.counts.ignores != ignores 
		    || fixture.counts.exceptions != exceptions )
		{
			fail("assertCount failed. Expected: (" 
				+ [ right, wrong, ignores, exceptions ] 
				+ ") actual:(" 
				+ [ fixture.counts.right, fixture.counts.wrong, fixture.counts.ignores, fixture.counts.exceptions ] 
				+ ").");
		}
	}
}
}
